#include "md5.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>

int short_ascii[63]= {0,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122};
int full_ascii[194]= {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,58,59,60,61,62,63,64,91,92,93,94,95,96,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255};
int short_ascii_lenght=63;
int full_ascii_lenght=194;

struct params{
    char **hash;
    int cantchar;
};
typedef struct params params;

pthread_t thread1, thread2, thread3, thread4;

void get_sum(char *input, char *output);

int test_ranges(char** values, int cantchar, int cantvalues, int *cant_found, int* array_1, int lenght_1, int* array_2, int lenght_2, int* array_3, int lenght_3, int* array_4, int lenght_4){
	char *input;
	input = (char*) malloc(5);
	input[4] = 0;
	int i,j,k,l,m;
	char *output;
	output = (char *) malloc(33);

	for ( l = 0; l < lenght_1; ++l)
		for ( k = 0; k < lenght_2; ++k)
			for ( j = 0; j < lenght_3; ++j)
				for ( i = 0; i < lenght_4; ++i){

					input[0] = (char) array_1[i];
					input[1] = (char) array_2[j];
					input[2] = (char) array_3[k];
					input[3] = (char) array_4[l];
					//printf("Input: %s", input);
                    get_sum(input, output);
                    for ( m = 0; m < cantvalues; ++m){
                        if (strcmp(output,values[m]) == 0) {
                            (*cant_found)++;
                            printf ("Hash: %s Contraseña: %.*s\n", values[m], cantchar, input);
                            if((*cant_found)==cantvalues)
                                return 1;
                        }
                    }
				}
    return 0;
}

void get_pwd(char **values, int cantchar, int cantvalues) {
    int cant_found=0;

    if(test_ranges(values, cantchar, cantvalues, &cant_found, short_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght));


    else if(test_ranges(values, cantchar, cantvalues, &cant_found, full_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght));
    else if(test_ranges(values, cantchar, cantvalues, &cant_found, short_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght));
    else if(test_ranges(values, cantchar, cantvalues, &cant_found, short_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght));
    else if(test_ranges(values, cantchar, cantvalues, &cant_found, short_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght));

    else if(test_ranges(values, cantchar, cantvalues, &cant_found, full_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght));
    else if(test_ranges(values, cantchar, cantvalues, &cant_found, full_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght));
    else if(test_ranges(values, cantchar, cantvalues, &cant_found, full_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght));
    else if(test_ranges(values, cantchar, cantvalues, &cant_found, short_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght));
    else if(test_ranges(values, cantchar, cantvalues, &cant_found, short_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght));
    else if(test_ranges(values, cantchar, cantvalues, &cant_found, short_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght));

    else if(test_ranges(values, cantchar, cantvalues, &cant_found, full_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght));
    else if(test_ranges(values, cantchar, cantvalues, &cant_found, full_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght));
    else if(test_ranges(values, cantchar, cantvalues, &cant_found, full_ascii, full_ascii_lenght, short_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght));
    else if(test_ranges(values, cantchar, cantvalues, &cant_found, short_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght));

    else if(test_ranges(values, cantchar, cantvalues, &cant_found, full_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght, full_ascii, full_ascii_lenght));
}
/*
void* run(void* ptr){
    params *x=ptr;
    get_pwd(x->hash, x->cantchar);
    free(x->hash);
    free(x);
    return 0;
}

void thread_get_pwd(char* hash, int cantchar){
    if(thread1 && thread2 && 0==pthread_kill(thread1, 0) && 0==pthread_kill(thread2, 0) && thread3 && thread4 && 0==pthread_kill(thread3, 0) && 0==pthread_kill(thread4, 0)){
        pthread_join( thread1, NULL);
        pthread_join( thread2, NULL);
        thread1=0;
        thread2=0;
        pthread_join( thread3, NULL);
        pthread_join( thread4, NULL);
        thread3=0;
        thread4=0;
    }

    params *param;
    param = (params*)malloc(sizeof(params));
    param->hash = (char*)malloc(33*sizeof(char));
    strcpy(param->hash, hash);
    param->cantchar=cantchar;

    if(!thread1 || 0!=pthread_kill(thread1, 0))
        pthread_create(&thread1, NULL, run, param);
    else if(!thread2 || 0!=pthread_kill(thread2, 0))
        pthread_create(&thread2, NULL, run, param);
    else if(!thread3 || 0!=pthread_kill(thread3, 0))
        pthread_create(&thread3, NULL, run, param);
    else if(!thread4 || 0!=pthread_kill(thread4, 0))
        pthread_create(&thread4, NULL, run, param);
}

*/
int main (int argc, char **argv) {
	char *arch = (char *) argv[1];
	FILE* archivo;
	int cantchar;

	if (strcmp(arch, "passwd_1") == 0)
		cantchar = 1;
	if (strcmp(arch, "passwd_2") == 0)
		cantchar = 2;
	if (strcmp(arch, "passwd_3") == 0)
		cantchar = 3;
	if (strcmp(arch, "passwd_4") == 0)
		cantchar = 1;

	archivo = fopen(arch,"r");
	int i=0;
	char *values[32];
	while (!feof(archivo)) {
        values[i]=(char*)malloc(33*sizeof(char));
		if (fread(values[i], 1, 33, archivo) == 33) {
			values[i][32]='\0';
		}
		i++;
	}

	get_pwd(values, cantchar, i-1);

	return 0;
}
